/*	http://code.google.com/p/wamon/
 *	Windows Activity Monitor - Monitors user's activity on the computer, 
 *	tracks active windows and processes, allows table and chart visualization.
 *	Copyright (C) 2009  Archae s.r.o. (http://archaedev.com/)
 *
 *	This program is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reflection;
using Microsoft.Win32;
using NetFwTypeLib;
using System.Threading;

namespace Archae.Wamon
{
	class Program
	{
		static void Main(string[] args)
		{
			if (args.Length == 0)
				return;
			if (args[0] == "/daemon")
				new Program();
			else if (args[0] == "/stats")
				Process.Start("http://localhost:" + DB.Singleton.Port + "/stats");
			else if (args[0] == "/install")
				Install();
			else if (args[0] == "/uninstall")
				Uninstall();
		}

		static void Install()
		{
			try
			{
				// Add a firewall exception
				Type type = Type.GetTypeFromCLSID(new Guid("{304CE942-6E39-40D8-943A-B913C40C9CD4}"));
				INetFwMgr firewallManager = (INetFwMgr)Activator.CreateInstance(type);
				type = Type.GetTypeFromProgID("HNetCfg.FwAuthorizedApplication");
				INetFwAuthorizedApplication authapp = (INetFwAuthorizedApplication)Activator.CreateInstance(type);
				authapp.Name = "Windows Activity Monitor";
				authapp.ProcessImageFileName = Assembly.GetExecutingAssembly().Location;
				authapp.Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL;
				authapp.IpVersion = NET_FW_IP_VERSION_.NET_FW_IP_VERSION_ANY;
				authapp.Enabled = true;
				firewallManager.LocalPolicy.CurrentProfile.AuthorizedApplications.Add(authapp);
			}
			catch (Exception e) { DB.Singleton.Log(e.ToString()); }
		}

		static void Uninstall()
		{
			try
			{
				// Add a firewall exception
				Type type = Type.GetTypeFromCLSID(new Guid("{304CE942-6E39-40D8-943A-B913C40C9CD4}"));
				INetFwMgr firewallManager = (INetFwMgr)Activator.CreateInstance(type);
				firewallManager.LocalPolicy.CurrentProfile.AuthorizedApplications.Remove(Assembly.GetExecutingAssembly().Location);
			}
			catch (Exception e) { DB.Singleton.Log(e.ToString()); }
		}

		private WamonHttp wamonHttp;
		private WamonDaemon wamonDaemon;
		private Thread mutexThread;

		private Program()
		{
			try
			{
				WebRequest.Create("http://localhost:" + DB.Singleton.Port + "/icon?process=IDLE").GetResponse();
				return; // If we can get a file from the service, it's running and we don't want to run twice
			}
			catch (Exception) { }
			if (!Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\wam"))
				Directory.CreateDirectory(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\wam");
			wamonHttp = new WamonHttp();
			wamonDaemon = new WamonDaemon();
			wamonHttp.Start();
			wamonDaemon.Start();
			mutexThread = new Thread(new ThreadStart(CheckMutexThread));
			mutexThread.Start();
			SystemEvents.SessionEnding += new SessionEndingEventHandler(SessionEnding);
		}

		private void CheckMutexThread()
		{
			try
			{
				while (true)
				{
					Thread.Sleep(1000);
					try
					{
						Mutex.OpenExisting("WamonReinstall").Close();
						StopAll("Mutex created");
						break;
					}
					catch (UnauthorizedAccessException) { StopAll("Mutex created (unauthorized)"); break; }
					catch (WaitHandleCannotBeOpenedException) { }
					catch (IOException) { }
				}
			}
			catch (ThreadAbortException) { }
		}

		private void SessionEnding(Object sender, SessionEndingEventArgs e)
		{
			if (e.Reason == SessionEndReasons.SystemShutdown)
				StopAll("System shutdown");
		}

		private void StopAll(string reason)
		{
			DB.Singleton.Log("Stopping: " + reason);
			new Thread(new ThreadStart(delegate()
				{
					// Wait a few seconds and if threads are not terminated, kill the process
					for (int i = 0; i < 20; i++)
					{
						Thread.Sleep(100);
						if (wamonHttp == null)
							return;
					}
					Process.GetCurrentProcess().Kill();
				})).Start();
			if (mutexThread != null)
			{
				mutexThread.Abort();
				mutexThread.Join();
				mutexThread = null;
			}
			if (wamonDaemon != null)
			{
				wamonDaemon.Stop();
				wamonDaemon = null;
			}
			if (wamonHttp != null)
			{
				wamonHttp.Stop();
				wamonHttp = null;
			}
		}
	}
}